home *** CD-ROM | disk | FTP | other *** search
- #include "rb_plugin.h"
- #include <Movies.h>
- #include <ImageCodec.h>
- #include <ImageCompression.h>
- #include <QuickTimeComponents.h>
- #include "QTEffect.h"
-
- //const int gNumberOfSteps = 30;
- const int kWidth = 320;
- const int kHeight = 200;
-
- static ImageDescriptionHandle QTEffects_MakeSampleDescription (EffectSequenceData *effect, short theWidth, short theHeight)
- {
- ImageDescriptionHandle mySampleDesc = NULL;
-
- // create a new sample description
- mySampleDesc = (ImageDescriptionHandle)NewHandleClear(sizeof(ImageDescription));
- if (mySampleDesc == NULL)
- return(NULL);
-
- // fill in the fields of the sample description
- (**mySampleDesc).idSize = sizeof(ImageDescription);
- (**mySampleDesc).cType = effect->theEffectType;
- (**mySampleDesc).vendor = kAppleManufacturer;
- (**mySampleDesc).temporalQuality = codecNormalQuality;
- (**mySampleDesc).spatialQuality = codecNormalQuality;
- (**mySampleDesc).width = theWidth;
- (**mySampleDesc).height = theHeight;
- (**mySampleDesc).hRes = 72L << 16;
- (**mySampleDesc).vRes = 72L << 16;
- (**mySampleDesc).frameCount = 1;
- (**mySampleDesc).depth = 0;
- (**mySampleDesc).clutID = -1;
-
- return(mySampleDesc);
- }
-
- static QTAtomContainer QTEffects_CreateTwoSourceEffectDescription (EffectData *effect, OSType theSourceName1, OSType theSourceName2)
- {
- QTAtomContainer myEffectDesc = NULL;
- OSType myType;
- OSErr myErr = noErr;
-
- // create a new, empty effect description
- myErr = QTNewAtomContainer(&myEffectDesc);
- if (myErr != noErr)
- goto bail;
-
- // create the effect ID atom: the atom type is kParameterWhatName, and the atom ID is kParameterWhatID
- myType = EndianU32_NtoB(effect->theEffectType);
- myErr = QTInsertChild(myEffectDesc, kParentAtomIsContainer, kParameterWhatName, kParameterWhatID, 0, sizeof(myType), &myType, NULL);
- if (myErr != noErr)
- goto bail;
-
- // add the first source
- myType = EndianU32_NtoB(theSourceName1);
- myErr = QTInsertChild(myEffectDesc, kParentAtomIsContainer, kEffectSourceName, 1, 0, sizeof(myType), &myType, NULL);
- if (myErr != noErr)
- goto bail;
-
- // add the second source
- myType = EndianU32_NtoB(theSourceName2);
- myErr = QTInsertChild(myEffectDesc, kParentAtomIsContainer, kEffectSourceName, 2, 0, sizeof(myType), &myType, NULL);
-
- bail:
- return(myEffectDesc);
- }
-
- static OSErr QTEffects_SetUpEffectSequence (EffectSequenceData *effect, CGrafPtr port, GDHandle portDevice)
- {
- OSErr myErr = noErr;
- ImageSequenceDataSource mySrc1 = 0;
- ImageSequenceDataSource mySrc2 = 0;
- ImageSequenceDataSource mySrc3 = 0;
- PixMapHandle mySrcPixMap;
- PixMapHandle myDstPixMap;
- /*
- // if an effect sequence is already set up, end it
- if (gCurrentState.fEffectSequenceID != 0L) {
- CDSequenceEnd(gCurrentState.fEffectSequenceID);
- gCurrentState.fEffectSequenceID = 0L;
- }
-
- // if there is a timebase already set up, dispose of it
- if (gCurrentState.fTimeBase != NULL) {
- DisposeTimeBase(gCurrentState.fTimeBase);
- gCurrentState.fTimeBase = NULL;
- }
- */
- // make an effects sequence
- HLock((Handle)effect->fEffectDescription);
-
- // prepare the decompression sequence for playback
- myErr = DecompressSequenceBeginS(
- &effect->fEffectSequenceID,
- effect->fSampleDescription,
- StripAddress(*effect->fEffectDescription),
- GetHandleSize(effect->fEffectDescription),
- port,
- portDevice,
- NULL,
- NULL,
- ditherCopy,
- NULL,
- 0,
- codecNormalQuality,
- NULL);
-
- HUnlock((Handle)effect->fEffectDescription);
- if (myErr != noErr)
- goto bail;
-
- // get the pixel maps for the GWorlds
- mySrcPixMap = GetGWorldPixMap(effect->fGW1);
- myDstPixMap = GetGWorldPixMap(effect->fGW2);
- if ((mySrcPixMap == NULL) || (myDstPixMap == NULL))
- goto bail;
-
- // make the first effect source
- if (effect->fGW1 == NULL)
- goto bail;
- myErr = MakeImageDescriptionForPixMap(mySrcPixMap, &effect->fGW1Desc);
- if (myErr != noErr)
- goto bail;
-
- myErr = CDSequenceNewDataSource(effect->fEffectSequenceID, &mySrc1, FOUR_CHAR_CODE('srcA'), 1, (Handle)effect->fGW1Desc, NULL, 0);
- if (myErr != noErr)
- goto bail;
-
- CDSequenceSetSourceData(mySrc1, GetPixBaseAddr(mySrcPixMap), (**effect->fGW1Desc).dataSize);
-
- // make the second effect source
- if (effect->fGW2 == NULL)
- goto bail;
- myErr = MakeImageDescriptionForPixMap(myDstPixMap, &effect->fGW2Desc);
- if (myErr != noErr)
- goto bail;
-
- myErr = CDSequenceNewDataSource(effect->fEffectSequenceID, &mySrc2, FOUR_CHAR_CODE('srcB'), 1, (Handle)effect->fGW2Desc, NULL, 0);
- if (myErr != noErr)
- goto bail;
-
- CDSequenceSetSourceData(mySrc2, GetPixBaseAddr(myDstPixMap), (**effect->fGW2Desc).dataSize);
-
- // create a new time base and associate it with the decompression sequence
- effect->fTimeBase = NewTimeBase();
- myErr = GetMoviesError();
- if (myErr != noErr)
- goto bail;
-
- SetTimeBaseRate(effect->fTimeBase, 0);
- myErr = CDSequenceSetTimeBase(effect->fEffectSequenceID, effect->fTimeBase);
-
- bail:
- return(myErr);
- }
-
- static OSErr QTEffects_RunEffect (EffectSequenceData *effect, TimeValue theTime)
- {
- OSErr myErr = noErr;
- ICMFrameTimeRecord myFrameTime;
-
- // assertions
- if ((effect->fEffectDescription == NULL) || (effect->fEffectSequenceID == 0L))
- goto bail;
-
- // set the timebase time to the step of the sequence to be rendered
- SetTimeBaseValue(effect->fTimeBase, theTime, effect->frames);
-
- myFrameTime.value.hi = 0;
- myFrameTime.value.lo = theTime;
- myFrameTime.scale = effect->frames;
- myFrameTime.base = 0;
- myFrameTime.duration = effect->frames;
- myFrameTime.rate = 0;
- myFrameTime.recordSize = sizeof(myFrameTime);
- myFrameTime.frameNumber = 1;
- myFrameTime.flags = icmFrameTimeHasVirtualStartTimeAndDuration;
- myFrameTime.virtualStartTime.lo = 0;
- myFrameTime.virtualStartTime.hi = 0;
- myFrameTime.virtualDuration = effect->frames;
-
- HLock((Handle)effect->fEffectDescription);
-
- myErr = DecompressSequenceFrameWhen(
- effect->fEffectSequenceID,
- StripAddress(*((Handle)effect->fEffectDescription)),
- GetHandleSize((Handle)effect->fEffectDescription),
- 0,
- 0,
- NULL,
- &myFrameTime);
-
- HUnlock((Handle)effect->fEffectDescription);
-
- if (myErr != noErr)
- goto bail;
-
- bail:
- return(myErr);
- }
-
- void BuildSMPTEEffect(EffectData *data, int id)
- {
- long myLong;
- OSType type;
-
- if (id >= 1 && id <= 100)
- type = 'smpt';
- else if (id >= 101 && id <= 200)
- type = 'smp2';
- else if (id >= 201 && id <= 300)
- type = 'smp3';
- else if (id >= 301)
- type = 'smp4';
-
- data->theEffectType = type;
- data->fEffectDescription = QTEffects_CreateTwoSourceEffectDescription(data, FOUR_CHAR_CODE('srcA'), FOUR_CHAR_CODE('srcB'));
- myLong = id;
- QTInsertChild(data->fEffectDescription,
- kParentAtomIsContainer,
- FOUR_CHAR_CODE('wpID'),
- 1,
- 0,
- sizeof(myLong),
- &myLong,
- NULL);
- }
-
- void BuildCrossFadeEffect(EffectData *data)
- {
- data->theEffectType = 'dslv';
- data->fEffectDescription = QTEffects_CreateTwoSourceEffectDescription(data, FOUR_CHAR_CODE('srcA'), FOUR_CHAR_CODE('srcB'));
- }
-
- /*
- void DoItAll(EffectData *data)
- {
- EffectObject obj;
-
- obj.fEffectSequenceID = 0;
-
- obj.fSampleDescription = QTEffects_MakeSampleDescription(&obj, kWidth, kHeight);;
- QTEffects_SetUpEffectSequence(&obj, nil, nil);
- QTEffects_RunEffect(&obj, 5);
- }
- */
-
- static GWorldPtr REALPictToGWorldPtr(REALpicture pic, const Rect &rBounds)
- {
- GWorldPtr gw;
- CGrafPtr oldPort;
- GDHandle oldDevice;
-
- GetGWorld(&oldPort, &oldDevice);
-
- NewGWorld(&gw, 16, &rBounds, nil, nil, 0);
- LockPixels(GetGWorldPixMap(gw));
-
- SetGWorld(gw, nil);
- EraseRect(&rBounds);
- REALDrawPicturePrimitive(pic, &rBounds, false);
-
- SetGWorld(oldPort, oldDevice);
-
- return gw;
- }
-
- void BuildEffectSquence(EffectSequenceData *data, EffectData *effect, REALpicture pic1, REALpicture pic2, int frames)
- {
- REALpictureDescription description;
- int w, h;
- Rect r;
-
- data->lastFrame = -1;
- data->currentFrame = 0;
- data->fTimeBase = nil;
-
- REALLockPictureDescription(pic1, &description);
-
- w = description.width;
- h = description.height;
-
- SetRect(&r, 0, 0, w, h);
-
- if (description.pictureType == pictureMacintoshGWorld)
- {
- data->pic1 = pic1;
- REALLockObject((REALobject) pic1);
- data->fGW1 = (GWorldPtr) description.pictureData;
- }
- else
- {
- data->pic1 = nil;
- data->fGW1 = REALPictToGWorldPtr(pic1, r);
- }
-
- REALLockPictureDescription(pic2, &description);
-
- if (description.pictureType == pictureMacintoshGWorld)
- {
- data->pic2 = pic2;
- REALLockObject((REALobject) pic2);
- data->fGW2 = (GWorldPtr) description.pictureData;
- }
- else
- {
- data->pic2 = nil;
- data->fGW2 = REALPictToGWorldPtr(pic2, r);
- }
-
- // copy effect to effectSequence
- data->theEffectType = effect->theEffectType;
- QTCopyAtom(effect->fEffectDescription, kParentAtomIsContainer, &data->fEffectDescription);
-
- data->frames = frames;
-
- data->fSampleDescription = QTEffects_MakeSampleDescription(data, w, h);
-
- NewGWorld(&data->fDest, 16, &r, nil, nil, 0);
- data->destPicture = REALBuildPictureFromGWorld(data->fDest, true);
-
- QTEffects_SetUpEffectSequence(data, data->fDest, GetGWorldDevice(data->fDest));
- }
-
- void BuildEffectSequenceFrame(EffectSequenceData *data, int frame)
- {
- Boolean bNeedsLock;
-
- if (GetPixelsState(GetGWorldPixMap(data->fDest)) & pixelsLocked)
- bNeedsLock = false;
- else
- bNeedsLock = true;
-
- if (bNeedsLock)
- LockPixels(GetGWorldPixMap(data->fDest));
- QTEffects_RunEffect(data, frame);
- REALPictureClearCache(data->destPicture);
- if (bNeedsLock)
- UnlockPixels(GetGWorldPixMap(data->fDest));
- }
-